package com.gt.quality.system.service.impl;

import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.http.Method;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.gt.quality.base.BusinessSelfException;
import com.gt.quality.config.ZhiPuAIConstant;
import com.gt.quality.system.service.ZhiPuAiProxyService;
import com.gt.quality.utils.FileCopyToLocal;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Flux;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * 万里悲秋常作客,百年多病独登台
 *
 * @author : makeJava
 */
@Component
@Slf4j
public class ZhiPuAiProxyManage implements ZhiPuAiProxyService {

    // 请自定义自己的业务id
    private static final String REQUEST_ID_TEMPLATE = "guo_tong_%d";

    private static final String COMPLETIONS_URL = "https://open.bigmodel.cn/api/paas/v4/chat/completions";

    @Resource(name = "useDialogue")
    private WebClient webClient;

    @Resource
    private FileCopyToLocal fileCopyToLocal;

    /**
     * 根据问题获取关联到要查询的表名
     */
    @Override
    public Object getSelectTableNames(String tableNames, String question) {
        List<Map<String, Object>> messages = new ArrayList<>();
        Map<String, Object> msgItem = new HashMap<>();
        msgItem.put("role", "user");
        msgItem.put("content", "请你作为数据分析师，" +
                               "现在数据库里面存在表这些：" + tableNames + ";帮助分析这个问题->'" + question + "';该问题的数据具体放在那些张表里面,输入格式返回为JSON,示例->[{'tableName':'table01'},{'tableName':'table02'}]]。");
        messages.add(msgItem);
        return messages;
    }


    @Override
    public List<Map<String, Object>> buildSqlParam(String tableInfos, String question) {
        List<Map<String, Object>> messages = new ArrayList<>();
        Map<String, Object> msgItem = new HashMap<>();
        msgItem.put("role", "user");
        msgItem.put("content", "请你作为数据分析师，" +
                               "现在数据库的表结构是这样：" + tableInfos + ";帮助查询出" + question + "，具体输入的内容为标准的SQL即可。");
        messages.add(msgItem);
        return messages;
    }

    /**
     * Description:
     *
     * @author: makeJava
     * @date: 2025-03-29 16:55:35
     */
    @Override
    public String handlerAiQuestion(String params, String question, boolean createSql) {
        Map<String, Object> body = new HashMap<>();
        body.put("model", "glm-4-flash");
        Object messages;
        if (createSql) {
            messages = buildSqlParam(params, question);
        } else {
            messages = getSelectTableNames(params, question);
        }
        body.put("messages", messages);
        body.put("request_id", String.format(REQUEST_ID_TEMPLATE, System.currentTimeMillis()));
        body.put("do_sample", true);
        body.put("stream", false);
        body.put("temperature", 0.95);
        body.put("max_tokens", 4095);
        Map<String, Object> responseFormat = new HashMap<>();
        responseFormat.put("type", "json_object");
        body.put("response_format", responseFormat);
        // function、retrieval、web_search。
        body.put("type", "web_search");

        String result = "null";
        try (HttpResponse response = HttpUtil.createRequest(Method.POST, COMPLETIONS_URL)
                .body(JSONUtil.toJsonStr(body))
                .header("Authorization", "Bearer " + ZhiPuAIConstant.ZHI_PU_AI_API_KEY)
                .execute()) {
            // 使用 try-with-resources 确保资源自动关闭
            result = response.body();
        } catch (Exception e) {
            log.error("调用接口失败: {}", e.getMessage(), e);
            return null;
        }
        log.info("调用接口返回: {}", result);
        return result;
    }


    /**
     * 从AI返回的JSON中解析表信息
     *
     * @param response AI返回的JSON字符串
     * @return 解析后的表信息字符串
     */
    @SuppressWarnings("unchecked")
    @Override
    public String parseTableFromResponse(String response) {
        try {
            Map<String, Object> responseMap = JSONUtil.toBean(response, Map.class);
            List<Map<String, Object>> choices = (List<Map<String, Object>>) responseMap.get("choices");
            if (choices != null && !choices.isEmpty()) {
                Map<String, Object> choice = choices.get(0);
                Map<String, Object> message = (Map<String, Object>) choice.get("message");
                if (message != null) {
                    String content = (String) message.get("content");
                    if (content.contains("[")) {
                        if (content.startsWith("\n")) {
                            content = content.replace("\n", "");
                        }
                        List<JSONObject> list = JSONUtil.toList(content, JSONObject.class);
                        return list.stream()
                                .map(jsonObject -> jsonObject.getStr("tableName"))
                                .collect(Collectors.joining(","));

                    }
                    log.info("解析JSON---->: {}", content);
                }
            }
        } catch (Exception e) {
            log.error("解析JSON失败: {}", e.getMessage(), e);
        }
        return null;
    }


    /**
     * 从AI返回的JSON中解析SQL
     *
     * @param response AI返回的JSON字符串
     * @return 解析后的SQL字符串
     */
    @SuppressWarnings("unchecked")
    @Override
    public String parseSqlFromResponse(String response) {
        try {
            // 将JSON字符串转换为Map对象
            Map<String, Object> responseMap = JSONUtil.toBean(response, Map.class);
            // 获取choices列表
            List<Map<String, Object>> choices = (List<Map<String, Object>>) responseMap.get("choices");
            // 如果choices列表不为空
            if (choices != null && !choices.isEmpty()) {
                // 获取第一个choice
                Map<String, Object> choice = choices.get(0);
                // 获取message
                Map<String, Object> message = (Map<String, Object>) choice.get("message");
                // 如果message不为空
                if (message != null) {
                    // 获取content
                    String content = (String) message.get("content");
                    // 如果content不为空
                    if (content != null) {
                        // 如果content以"\n{"开头
                        if (content.startsWith("\n{")) {
                            // 将content转换为Map对象
                            Map<String, Object> contentMap = JSONUtil.toBean((String) message.get("content"), Map.class);
                            // 获取answer
                            Object answer = contentMap.get("answer");
                            // 如果answer不为空
                            if (answer != null) {
                                // 返回answer
                                return answer.toString();
                            }
                            // 获取sql_query
                            Object sqlQuery = contentMap.get("sql_query");
                            // 如果sql_query不为空
                            if (sqlQuery != null) {
                                // 返回sql_query
                                return sqlQuery.toString();
                            }
                            // 获取query
                            Object query = contentMap.get("query");
                            // 返回query或contentMap
                            return Objects.requireNonNullElse(query, contentMap).toString();
                        }
                        // 将content中的"sql\n"替换为空字符串
                        content = content.replace("sql\n", "");
                        // 返回content
                        return content;
                    }

                }
            }
        } catch (Exception e) {
            // 记录错误日志
            log.error("解析JSON失败: {}", e.getMessage(), e);
        }
        // 返回null
        return null;
    }

    @Override
    public Flux<String> streamInvoke(String question) {
        // Create a map to store the request body
        Map<String, Object> body = new HashMap<>();
        // Set the model to "glm-4-flash"
        body.put("model", "glm-4-flash");
        // Create a list to store the questions
        List<Map<String, Object>> questionList = getAiRoleAndUserBody(question);
        // Add the list of questions to the request body
        body.put("messages", questionList);
        // Set the request_id to a random UUID
        body.put("request_id", UUID.randomUUID().toString());
        // Set the do_sample to true
        body.put("do_sample", true);
        // Set the temperature to 0.95
        body.put("temperature", 0.95);
        // Set the stream to true
        body.put("stream", true);
        // Set the max_tokens to 4095
        body.put("max_tokens", 4095);
        // Create a map to store the response format
        Map<String, Object> responseFormat = new HashMap<>();
        // Set the type of the response format to "json_object"
        responseFormat.put("type", "json_object");
        // Add the response format to the request body
        body.put("response_format", responseFormat);
        // function、retrieval、web_search。
        body.put("type", "web_search");
        try {
            HttpHeaders headers = new HttpHeaders();
            headers.set("Content-Type", MediaType.APPLICATION_JSON_VALUE);
            headers.set("Accept", MediaType.TEXT_EVENT_STREAM_VALUE);
            headers.set("Accept-Encoding", "gzip, deflate, br");
            headers.set("Connection", "keep-alive");
            headers.set("Authorization", "Bearer " + ZhiPuAIConstant.ZHI_PU_AI_API_KEY);
            // 数据库对话分析
            return webClient.post()
                    .headers(httpHeaders -> httpHeaders.putAll(headers))
                    .bodyValue(JSONUtil.toJsonStr(body))
                    .retrieve().bodyToFlux(String.class)
                    .map(s -> s.replaceAll("data:", ""));
        } catch (Throwable e) {
            log.error(e.getMessage(), e);
            return Flux.error(new BusinessSelfException("系统走神了，请稍后再试..."));
        }
    }

    /**
     * 获取ai角色和用户信息
     *
     * @param question question
     * @return
     */
    private List<Map<String, Object>> getAiRoleAndUserBody(String question) {
        List<Map<String, Object>> questionList = new ArrayList<>();
        // Create a map to store the first question
        Map<String, Object> questionMap = new HashMap<>();
        // Set the role of the first question to "system"
        questionMap.put("role", "system");
        // Set the content of the first question
        questionMap.put("content", "你是一个乐于回答各种问题的小助手，你的任务是提供专业、准确、有洞察力的建议。");
        // Add the first question to the list
        questionList.add(questionMap);
        // Create a map to store the second question
        Map<String, Object> questionMap2 = new HashMap<>();
        // Set the role of the second question to "user"
        questionMap2.put("role", "user");
        // Set the content of the second question
        questionMap2.put("content", question);
        // Add the second question to the list
        questionList.add(questionMap2);
        return questionList;
    }

    /**
     * {"id":"1745391061_39b5188d68484bbda659f4693ce65fd7",
     * "object":"file","bytes":3656,
     * "filename":"仿真示例.txt",
     * "purpose":"file-extract","created_at":1745391061}
     */
    @Override
    public Object fileHandler(MultipartFile file) {
        File realFile = fileCopyToLocal.copyToLocalCallBackFile(file);
        String result = null;
        // 文件上传
        try (HttpResponse response = HttpUtil.createRequest(Method.POST, ZhiPuAIConstant.ZHI_PU_AI_FILE_HANDLER_URL)
                .form("file", realFile)
                .form("purpose", "file-extract")
                .header("Authorization", "Bearer " + ZhiPuAIConstant.ZHI_PU_AI_API_KEY)
                .header("Content-Type", MediaType.MULTIPART_FORM_DATA_VALUE)
                .execute()) {
            // 文件内容提取
            result = response.body();
            JSONObject responseBody = JSONUtil.parseObj(result);
            String fileId = responseBody.getStr("id");
            String body = HttpUtil.createRequest(Method.GET, String.format(ZhiPuAIConstant.ZHI_PU_AI_FILE_ETL_URL, fileId)).
                    header("Authorization", "Bearer " + ZhiPuAIConstant.ZHI_PU_AI_API_KEY)
                    .execute().body();
            com.alibaba.fastjson2.JSONObject jsonObject = com.alibaba.fastjson2.JSONObject.parseObject(body);
            result = jsonObject.getString("content");
        } catch (Exception e) {
            log.error("调用接口失败: {}", e.getMessage(), e);
            return result;
        }
        return result;
    }

    @Override
    public Object generationsVide(String urlImage, String model, String quality, String size, int fps, boolean withAudio, String requestId, String prompt) {
        JSONObject body = new JSONObject();
        body.set("model", model);
        body.set("quality", quality);
        body.set("size", size);
        body.set("fps", fps);
        body.set("with_audio", withAudio);
        body.set("request_id", requestId);
        body.set("prompt", prompt);
        body.set("image_url", urlImage);
        body.set("duration", 10);
        String result = null;
        // 文件上传
        try (HttpResponse response = HttpUtil.createRequest(Method.POST, ZhiPuAIConstant.ZHI_PU_AI_VIDEOS_URL)
                .body(body.toString())
                .header("Authorization", "Bearer " + ZhiPuAIConstant.ZHI_PU_AI_API_KEY)
                .header("Content-Type", MediaType.APPLICATION_JSON_VALUE)
                .execute()) {
            // 文件内容提取
            result = response.body();
            System.out.println(requestId);
            System.out.println("-----------------------");
            System.out.println(result);
        } catch (Exception e) {
            log.error("调用接口失败: {}", e.getMessage(), e);
        }
        return result;
    }

    @Override
    public Object generationsVideById(String id) {
        String result = null;
        // 文件列表获取生成的视频
        try (HttpResponse response = HttpUtil.createRequest(Method.GET, ZhiPuAIConstant.ZHI_PU_AI_VIDEOS_GET_URL.replace("{id}", id))
                .header("Authorization", "Bearer " + ZhiPuAIConstant.ZHI_PU_AI_API_KEY)
                .header("Content-Type", MediaType.APPLICATION_JSON_VALUE)
                .execute()) {
            // 文件内容提取
            result = response.body();
            System.out.println(id);
            System.out.println("-----------------------");
            System.out.println(result);
        } catch (Exception e) {
            log.error("调用接口失败: {}", e.getMessage(), e);
        }
        return result;
    }


}
